/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: workflow.hpp
 */

#ifndef _WORKFLOW_HPP_
#define _WORKFLOW_HPP_

#include <iostream>
#include <vector>
#include <string>
#include <exception>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>

#include "task_descriptor.hpp"
#include "workflow_exception.hpp"

//-----------------------------------------------------------------------------
// Enum, struct, aliases
namespace middleware {
typedef unsigned int WorkflowId;
}
//-----------------------------------------------------------------------------
// Constants
namespace middleware {
/*!
 * Represents the maximun ID assignable to a workflow.
 */
const unsigned int kMaxWorkflowID = 16000;
/*!
 * Represents the minimum ID assignable to a workflow.
 */
const unsigned int kMinWorkflowID = 1;
}
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
/*!
 * Defines all elements for a workflow of tasks.
 */
class Workflow {
public:
	typedef std::allocator< TaskDescriptor > Allocator;
	typedef std::vector< TaskDescriptor >::iterator TaskCollectionIterator;
	typedef std::vector< TaskDescriptor >::const_iterator
			TaskCollectionConstIterator;
	typedef unsigned int SizeType;
	typedef Allocator::reference Reference;
	typedef Allocator::const_reference ConstReference;
	/*!
	 * Builds a workflow with empty task deque.
	 */
	Workflow();
	/*!
	 * Creates a workflow from another one.
	 */
	Workflow(const Workflow& workflow);
	/*!
	 * Destructor.
	 */
	virtual ~Workflow();
	/*!
	 * Gets workflow ID.
	 */
	WorkflowId get_id() const {
		return this->_id;
	}
	/*!
	 * Sets workflow ID: this function should not be used because
	 * WorkflowDescriptor already thinks about this, an id conflict might
	 * occur if the id would be set manually.
	 */
	void set_id(WorkflowId id) {
		this->_id = id;
	}
	/*!
	 * Gets iterator to tasks starting from top.
	 */
	TaskCollectionIterator begin() {
		return this->_tasks.begin();
	}
	/*!
	 * Gets const iterator to tasks starting from top.
	 */
	TaskCollectionConstIterator begin() const {
		return this->_tasks.begin();
	}
	/*!
	 * Gets iterator to tasks starting from bottom.
	 */
	TaskCollectionIterator end() {
		return this->_tasks.end();
	}
	/*!
	 * Gets const iterator to tasks starting from bottom.
	 */
	TaskCollectionConstIterator end() const {
		return this->_tasks.end();
	}
	/*!
	 * Causes the collection of tasks to be totally overwritten with the new
	 * elements in the passed collection iterators. A copy of passed
	 * elements is performed. An stl container is preferred and TaskDescriptor
	 * type must be provided for elements in passed container.
	 */
	void assign(TaskCollectionConstIterator first,
			TaskCollectionConstIterator last);
	/*!
	 * Pushes a new task to the bottom of the collection.
	 */
	void push_back(ConstReference task);
	/*!
	 * Gets a reference to the task specifying its ID.
	 */
	Reference at_id(TaskId id) throw(WorkflowException);
	/*!
	 * Accessor by position. Gets the reference.
	 */
	Reference operator[](SizeType position);
	/*!
	 * Accessor by position. Gets the const reference.
	 */
	ConstReference operator[](SizeType position) const;
	/*!
	 * Clears collection
	 */
	void clear();
	/*!
	 * Returns size.
	 */
	SizeType size() const;
	/*!
	 * Tells whether the collection is empty.
	 */
	bool emtpy() const;
protected:
	/*!
	 * Represents the unique reference to this task.
	 */
	WorkflowId _id;
	/*!
	 * Represents the type of task, it can be an executable or a bash command.
	 */
	std::vector< TaskDescriptor > _tasks;
private:
	friend class boost::serialization::access;
	/*!
	 * BOOST serialization function.
	 */
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version) {
		ar & BOOST_SERIALIZATION_NVP(_tasks);
		ar & _id;
	}
	/*!
	 * Gets a unique id for the task.
	 */
	WorkflowId createID();
}; /* Workflow */
} /* middleware */

#endif
